; docformat = 'rst'
;
;+
;
; :Purpose:
;   Calculate running mean of input array
;
; :Inputs:
;   Var_in: input array
;
; :Keywords:
;   nAv: (required, input), number of elements to include in averaging window
;   endNan: (optional), use !values.f_nan  for end members
;   minElements: (optional), minimum elements required to calculate a mean
;   total: (optional), calculate running total, instead of running mean
;
; :Example::
;   IDL> x=findgen(100)
;   IDL> x_rm=mr_runningmean(x, nAv=10, minElements=5, /endNan)
;
; :History:
; 	Written by: Matt Rigby, University of Bristol, Jul 16, 2013
;
;-
Function mr_runningmean, var_in, nAv=nAv, endnan=endnan, minelements=minelements, total=total

  compile_opt idl2
  on_error, 2

  var=reform(var_in)

  if total(finite(var)) gt 0 then begin

    nD=size(var, /n_dimensions)
    
    if nD eq 1 then begin
    
      TimeSize=long(n_elements(var))
      nAv=long(nAv)
      if keyword_set(minelements) eq 0 then minelements=nav
      
      if 2*fix(nAv/2) eq nav then begin
        nBelow=long(nAv/2)
        nAbove=long(nAv/2-1)
      endif else begin
        nBelow=long(nAv/2)
        nAbove=long(nAv/2)
      endelse
      
      VarRM=replicate(!values.f_nan, TimeSize)
      
      ;check for starting and trailing nan
      StartI=-1L
      repeat startI+=1L until finite(var[StartI])
      EndI=TimeSize
      repeat EndI-=1L until finite(var[EndI])
  
      If total(finite(Var[StartI:StartI+nAv-1])) gt minelements then begin
          if keyword_set(endnan) then begin
            VarRm[StartI:StartI+nBelow]=!values.f_nan
            if keyword_set(total) then begin
              VarRM[StartI+nbelow]=total(Var[StartI:StartI+nAv-1], /nan)
            endif else begin
              VarRM[StartI+nbelow]=mean(Var[StartI:StartI+nAv-1], /nan)              
            endelse
          endif else begin
            if keyword_set(total) then begin
              VarRm[StartI:StartI+nBelow]=total(Var[StartI:StartI+nAv-1], /nan) 
            endif else begin
              VarRm[StartI:StartI+nBelow]=mean(Var[StartI:StartI+nAv-1], /nan)             
            endelse
          endelse
      endif else begin
           VarRm[StartI:StartI+nBelow]=!values.f_nan
      Endelse
      
      If total(finite(Var[EndI-nAv+1:EndI])) gt minelements then begin
          if keyword_set(endnan) then begin
            VarRm[EndI+1-nAbove:EndI]=!values.f_nan
            ;VarRm[TimeSize-nAbove]=mean(Var[TimeSize-nAv:TimeSize-1], /nan)
          endif else begin
            if keyword_set(total) then begin
              VarRm[EndI+1-nAbove:EndI]=total(Var[EndI+1-nAv:EndI], /nan)
            endif else begin
              VarRm[EndI+1-nAbove:EndI]=mean(Var[EndI+1-nAv:EndI], /nan)
            endelse
          Endelse
      Endif else begin
        VarRm[EndI+1-nAbove:EndI]=!values.f_nan
      Endelse
      
      For n=StartI+nBelow+1L, EndI+1L-nAbove-1L do begin
        If total(finite(Var[n - nBelow : n + nAbove])) ge minelements then begin
          if keyword_set(total) then begin
            VarRM[n]=total(Var[n - nBelow : n + nAbove], /nan)
          endif else begin
            VarRM[n]=mean(Var[n - nBelow : n + nAbove], /nan)
          endelse
        endif else begin
          VarRM[n]=!values.f_nan
        endelse
      Endfor
  
    endif else begin
    
      TimeSize=long(n_elements(var[0, *]))
      nAv=long(nAv)
      minelements=nav
      
      if 2*fix(nAv/2) eq nav then begin
        nBelow=long(nAv/2)
        nAbove=long(nAv/2-1)
      endif else begin
        nBelow=long(nAv/2)
        nAbove=long(nAv/2)
      endelse
      
      VarRM=replicate(!values.f_nan, TimeSize)
      
      ;check for starting and trailing nan
      StartI=-1L
      repeat startI+=1L until total(finite(var[*, StartI])) gt 0
      EndI=TimeSize
      repeat EndI-=1L until total(finite(var[*, EndI])) gt 0
      
      If total(finite(Var[*, StartI:StartI+nAv-1])) gt minelements*nD then begin
          if keyword_set(endnan) then begin
            VarRm[StartI:StartI+nBelow]=!values.f_nan
            if keyword_set(total) then begin
              VarRM[StartI+nbelow]=total(Var[*, StartI:StartI+nAv-1], /nan)
            endif else begin
              VarRM[StartI+nbelow]=mean(Var[*, StartI:StartI+nAv-1], /nan)
            endelse
          endif else begin
            if keyword_set(total) then begin
              VarRm[StartI:StartI+nBelow]=total(Var[*, StartI:StartI+nAv-1], /nan) 
            endif else begin
              VarRm[StartI:StartI+nBelow]=mean(Var[*, StartI:StartI+nAv-1], /nan)
            endelse
          endelse
      endif else begin
           VarRm[StartI:StartI+nBelow]=!values.f_nan
      Endelse
      
      If total(finite(Var[*, EndI-nAv+1:EndI])) gt minelements*nD then begin
          if keyword_set(endnan) then begin
            VarRm[EndI+1-nAbove:EndI]=!values.f_nan
            ;VarRm[TimeSize-nAbove]=mean(Var[TimeSize-nAv:TimeSize-1], /nan)
          endif else begin
            if keyword_set(total) then begin
              VarRm[EndI+1-nAbove:EndI]=total(Var[*, EndI+1-nAv:EndI], /nan)
            endif else begin
              VarRm[EndI+1-nAbove:EndI]=mean(Var[*, EndI+1-nAv:EndI], /nan)
            endelse
          Endelse
      Endif else begin
        VarRm[EndI+1-nAbove:EndI]=!values.f_nan
      Endelse
      
      For n=StartI+nBelow+1L, EndI+1L-nAbove-1L do begin
        If total(finite(Var[*, n - nBelow : n + nAbove])) ge minelements*nD then begin
          if keyword_set(total) then begin
            VarRM[n]=total(Var[*, n - nBelow : n + nAbove], /nan)
          endif else begin
            VarRM[n]=mean(Var[*, n - nBelow : n + nAbove], /nan)
          endelse
        endif else begin
           VarRM[n]=!values.f_nan
        endelse
      Endfor
    
    Endelse
    
    Var=VarRM
  
  endif

  return, var

End